package com.le.tester.book.effectivejava3rdchinese.secondReading.l10;

import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * createTime：2024-08-15 15:02
 * description：号码构建equals，每次重写equals方法，必须重写hashCode方法
 */
//implements Cloneable 代表可以被克隆
public class PhoneNumber implements Cloneable, Comparable<PhoneNumber> {

    private final short areaCode, prefix, lineNum;

    public static final Comparator<PhoneNumber> COMPARATOR = Comparator.comparingInt((PhoneNumber pn) -> pn.areaCode)
            .thenComparingInt(pn -> pn.prefix).thenComparingInt(pn -> pn.lineNum);

    public PhoneNumber(int areaCode, int prefix, int lineNum) {
        this.areaCode = rangeCheck(areaCode, 999, "area code");
        this.prefix = rangeCheck(prefix, 999, "prefix");
        this.lineNum = rangeCheck(lineNum, 9999, "line num");
    }

    private static short rangeCheck(int val, int max, String arg) {
        if (val < 0 || val > max) {
            throw new IllegalArgumentException();
        }
        return (short) val;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == this) {
            return true;
        }

        if (!(obj instanceof PhoneNumber)) {
            return false;
        }

        PhoneNumber pn = (PhoneNumber) obj;
        return pn.lineNum == lineNum && pn.prefix == prefix && pn.areaCode == areaCode;
    }
//never use
//    @Override
//    public int hashCode() {
//        return 42;
//    }


    //Typical hashCode method
//    @Override
//    public int hashCode() {
//        int result = Short.hashCode(areaCode);
//        result = 31 * result + Short.hashCode(prefix);
//        result = 31 * result + Short.hashCode(lineNum);
//        return result;
//        Hashing
//    }


    //不考虑性能时候的hash
    //不要排除hash中需要的属性，唯一性比性能更重要一些
    @Override
    public int hashCode() {
        return Objects.hash(lineNum, prefix, areaCode);
    }

    //重写object的clone方法，需要声明继承了接口cloneable，鸡肋设计，真不建议重写或者使用这个克隆方法
    @Override
    protected PhoneNumber clone() throws CloneNotSupportedException {
        //源头进行了类的转换，避免客户端转换的需要
        return (PhoneNumber) super.clone();
    }

    //类中的多个属性比较


    public static void main(String[] args) {


        //当是同一个hashCode的时候，将会返回同一个实例
        //new PhoneNumber()
        Map<PhoneNumber, String> m = new HashMap<>();
        m.put(new PhoneNumber(707, 867, 5309), "Jenny");


        System.out.println(m.get(new PhoneNumber(707, 867, 5309)));
    }

    @Override
    public int compareTo(PhoneNumber pn) {
//        int result = Short.compare(areaCode, pn.areaCode);
//        if (0 == result) {
//            result = Short.compare(prefix, pn.prefix);
//            if (0 == result) {
//                result = Short.compare(lineNum, pn.lineNum);
//            }
//        }
//        return result;
        return COMPARATOR.compare(this, pn);
    }

    public static void orderHashCode() {
        //不要这么做，可能会丢失精度
        //Comparator<Object> hashCode = (o1, o2) -> o1.hashCode() - o2.hashCode();
        //帮你做了精度丢失预判
        Comparator<Object> hashCode = Comparator.comparingInt(Object::hashCode);
    }
}
